#include "users.h"
#include "hashtables.h"
#include "extern.h"
#include "net.h"
#include "critical.h"

int client_init_hashtable (void)
{
	clientstb = HashTable_New (ServerConf.MaxClients);
	if (clientstb == NULL)
		return -1;

	HashTable_SetMethods (clientstb, client_compare, client_get_hash);
	return 0;
}

int client_compare (void* E1, void* E2)
{
	Client* client = E1;
	const char*	key = E2;

	return (strncmp (client->user, key, strlen (client->user)));
}

int client_get_hash (HashTable* htb, void* element)
{
	Client *client = element;
	return (hash_string (client->user, htb->size));
}

Client* client_new (int sock, char nick[NICKSIZE], char user[USERSIZE], char host[HOSTSIZE], int level)
{
 Client *client = malloc (sizeof (*client));
	if (client != NULL)
	{
		client->Socket.Socket = sock;
		if (MUTEX_INIT(client->Socket.mutex) != 0)
		{
			printf ("Mutex init error\n");
			free (client);
			client = NULL;
		}
		else
		{
			client->id = hash_string (client->user, clientstb->size);
			strncpy (client->nick, nick, NICKSIZE);
			strncpy (client->user, user, USERSIZE);
			strncpy (client->host, host, HOSTSIZE);
			client->status = 0x0;
			client->level = level;
			client->cash = 0;
			client->channels = List_New();
			if (client->channels == NULL)
			{
				printf ("ClientChannels not created\n");
				pthread_mutex_destroy (&client->Socket.mutex);
				close (client->Socket.Socket);
				free (client);
				client = NULL;
			}
		}
	}

 return (client);
}

void client_del (const char* user)
{
 Client* client = NULL;

	client = HashTable_Pop (clientstb, user);
	if (client != NULL)
	{
		List_Destroy (&client->channels);
		free (client);
		client = NULL;
	}
}


Peer* peer_new (struct sockaddr_in sin, int Socket)
{
 Peer* peer = malloc (sizeof (*peer));
	if (peer != NULL)
	{
		peer->sin = sin;
		peer->Socket = Socket;
	}

 return (peer);
}

void peer_clear (Peer **peer)
{
	free (*peer);
	*peer = NULL;
}

void client_chan_add (Client* client, const char* chname)
{
  ClientChannel *clchannel = malloc (sizeof (*clchannel));

	if (clchannel != NULL)
	{
		strncpy(clchannel->name, chname, sizeof(clchannel->name));
		clchannel->level = client->level;
		List_PushTail (client->channels, clchannel);
	}
}

void client_chan_del (Client* client, const char* chname)
{
	ClientChannel *clchannel = NULL;

	LIST_FOREACH (clchannel, client->channels){
		if (strncmp (clchannel->name, chname, sizeof (clchannel->name)) == 0){
			List_Del (client->channels, &client->channels->iter);
			break;
		}
	}

}
